package com.cbtx.utils

import android.Manifest
import android.annotation.SuppressLint
import android.content.Context
import android.content.pm.PackageManager
import android.net.wifi.WifiInfo
import android.net.wifi.WifiManager
import android.os.Build
import android.provider.Settings
import android.text.TextUtils
import android.util.Log
import com.blankj.utilcode.util.LogUtils
import java.io.*
import java.net.InetAddress
import java.net.NetworkInterface
import java.net.SocketException
import java.util.*

/**
 * author : joker.peng
 * e-mail : joker@fiture.com
 * date   : 2021/7/1 2:11 PM
 * desc   :
 */
object DeviceUtil {

    private var serial: String? = null

    fun getMac(context: Context): String? {
        val strMac: String?
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            Log.e("=====", "6.0以下")
            ////Toast.makeText(context, "6.0以下", ////Toast.LENGTH_SHORT).show();
            strMac = getLocalMacAddressFromWifiInfo(context)
            return strMac
        } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N
            && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
        ) {
            Log.e("=====", "6.0以上7.0以下")
            ////Toast.makeText(context, "6.0以上7.0以下", ////Toast.LENGTH_SHORT).show();
            strMac = getMacAddress(context)
            return strMac
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            Log.e("=====", "7.0以上")
            return if (!TextUtils.isEmpty(getMacAddress())) {
                Log.e("=====", "7.0以上1")
                ////Toast.makeText(context, "7.0以上1", //Toast.LENGTH_SHORT).show();
                strMac = getMacAddress()
                strMac
            } else if (!TextUtils.isEmpty(getMachineHardwareAddress())) {
                Log.e("=====", "7.0以上2")
                //Toast.makeText(context, "7.0以上2", //Toast.LENGTH_SHORT).show();
                strMac = getMachineHardwareAddress()
                strMac
            } else {
                Log.e("=====", "7.0以上3")
                //Toast.makeText(context, "7.0以上3", ////Toast.LENGTH_SHORT).show();
                strMac = getLocalMacAddressFromBusybox()
                strMac
            }
        }
        return "02:00:00:00:00:00"
    }

    /**
     * 根据wifi信息获取本地mac
     * @param context
     * @return
     */
    fun getLocalMacAddressFromWifiInfo(context: Context): String? {
        val wifi = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
        val winfo = wifi.connectionInfo
        return winfo.macAddress
    }

    /**
     * android 6.0及以上、7.0以下 获取mac地址
     *
     * @param context
     * @return
     */
    fun getMacAddress(context: Context): String? {

        // 如果是6.0以下，直接通过wifimanager获取
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            val macAddress0 = getMacAddress0(context)
            if (!TextUtils.isEmpty(macAddress0)) {
                return macAddress0
            }
        }
        var str = ""
        var macSerial = ""
        try {
            val pp = Runtime.getRuntime().exec(
                "cat /sys/class/net/wlan0/address"
            )
            val ir = InputStreamReader(pp.inputStream)
            val input = LineNumberReader(ir)
            while (null != str) {
                str = input.readLine()
                if (str != null) {
                    macSerial = str.trim { it <= ' ' } // 去空格
                    break
                }
            }
        } catch (ex: Exception) {
            Log.e("----->" + "NetInfoManager", "getMacAddress:$ex")
        }
        if (macSerial == null || "" == macSerial) {
            try {
                return loadFileAsString("/sys/class/net/eth0/address")
                    .toUpperCase().substring(0, 17)
            } catch (e: Exception) {
                e.printStackTrace()
                Log.e(
                    "----->" + "NetInfoManager",
                    "getMacAddress:$e"
                )
            }
        }
        return macSerial
    }

    private fun getMacAddress0(context: Context): String {
        if (isAccessWifiStateAuthorized(context)) {
            val wifiMgr = context
                .getSystemService(Context.WIFI_SERVICE) as WifiManager
            var wifiInfo: WifiInfo? = null
            try {
                wifiInfo = wifiMgr.connectionInfo
                return wifiInfo.macAddress
            } catch (e: Exception) {
                Log.e(
                    "----->" + "NetInfoManager",
                    "getMacAddress0:$e"
                )
            }
        }
        return ""
    }

    /**
     * Check whether accessing wifi state is permitted
     *
     * @param context
     * @return
     */
    private fun isAccessWifiStateAuthorized(context: Context): Boolean {
        return if (PackageManager.PERMISSION_GRANTED == context
                .checkCallingOrSelfPermission("android.permission.ACCESS_WIFI_STATE")
        ) {
            Log.e(
                "----->" + "NetInfoManager", "isAccessWifiStateAuthorized:"
                        + "access wifi state is enabled"
            )
            true
        } else false
    }

    @Throws(Exception::class)
    private fun loadFileAsString(fileName: String): String {
        val reader = FileReader(fileName)
        val text = loadReaderAsString(reader)
        reader.close()
        return text
    }

    @Throws(Exception::class)
    private fun loadReaderAsString(reader: Reader): String {
        val builder = StringBuilder()
        val buffer = CharArray(4096)
        var readLength = reader.read(buffer)
        while (readLength >= 0) {
            builder.append(buffer, 0, readLength)
            readLength = reader.read(buffer)
        }
        return builder.toString()
    }

    /**
     * 根据IP地址获取MAC地址
     *
     * @return
     */
    fun getMacAddress(): String? {
        var strMacAddr: String? = null
        try {
            // 获得IpD地址
            val ip = getLocalInetAddress()
            val b = NetworkInterface.getByInetAddress(ip)
                .hardwareAddress
            val buffer = StringBuffer()
            for (i in b.indices) {
                if (i != 0) {
                    buffer.append(':')
                }
                val str = Integer.toHexString(b[i].toInt() and 0xFF)
                buffer.append(if (str.length == 1) "0$str" else str)
            }
            strMacAddr = buffer.toString().toUpperCase()
        } catch (e: Exception) {
        }
        return strMacAddr
    }

    /**
     * 获取移动设备本地IP
     *
     * @return
     */
    private fun getLocalInetAddress(): InetAddress? {
        var ip: InetAddress? = null
        try {
            // 列举
            val en_netInterface = NetworkInterface
                .getNetworkInterfaces()
            while (en_netInterface.hasMoreElements()) { // 是否还有元素
                val ni = en_netInterface
                    .nextElement() as NetworkInterface // 得到下一个元素
                val en_ip = ni.inetAddresses // 得到一个ip地址的列举
                while (en_ip.hasMoreElements()) {
                    ip = en_ip.nextElement()
                    ip = if (!ip.isLoopbackAddress
                        && ip.hostAddress.indexOf(":") == -1
                    ) break else null
                }
                if (ip != null) {
                    break
                }
            }
        } catch (e: SocketException) {
            e.printStackTrace()
        }
        return ip
    }

    /**
     * 获取本地IP
     *
     * @return
     */
    private fun getLocalIpAddress(): String? {
        try {
            val en = NetworkInterface
                .getNetworkInterfaces()
            while (en.hasMoreElements()) {
                val intf = en.nextElement()
                val enumIpAddr = intf
                    .inetAddresses
                while (enumIpAddr.hasMoreElements()) {
                    val inetAddress = enumIpAddr.nextElement()
                    if (!inetAddress.isLoopbackAddress) {
                        return inetAddress.hostAddress.toString()
                    }
                }
            }
        } catch (ex: SocketException) {
            ex.printStackTrace()
        }
        return null
    }

    /**
     * android 7.0及以上 （2）扫描各个网络接口获取mac地址
     *
     */
    /**
     * android 7.0及以上 （2）扫描各个网络接口获取mac地址
     *
     */
    /**
     * 获取设备HardwareAddress地址
     *
     * @return
     */
    fun getMachineHardwareAddress(): String? {
        var interfaces: Enumeration<NetworkInterface?>? = null
        try {
            interfaces = NetworkInterface.getNetworkInterfaces()
        } catch (e: SocketException) {
            e.printStackTrace()
        }
        var hardWareAddress: String? = null
        var iF: NetworkInterface? = null
        if (interfaces == null) {
            return null
        }
        while (interfaces.hasMoreElements()) {
            iF = interfaces.nextElement()
            try {
                hardWareAddress = bytesToString(iF!!.hardwareAddress)
                if (hardWareAddress != null) break
            } catch (e: SocketException) {
                e.printStackTrace()
            }
        }
        return hardWareAddress
    }

    /***
     * byte转为String
     *
     * @param bytes
     * @return
     */
    private fun bytesToString(bytes: ByteArray?): String? {
        if (bytes == null || bytes.size == 0) {
            return null
        }
        val buf = StringBuilder()
        for (b in bytes) {
            buf.append(String.format("%02X:", b))
        }
        if (buf.length > 0) {
            buf.deleteCharAt(buf.length - 1)
        }
        return buf.toString()
    }

    /**
     * android 7.0及以上 （3）通过busybox获取本地存储的mac地址
     *
     */

    /**
     * android 7.0及以上 （3）通过busybox获取本地存储的mac地址
     *
     */
    /**
     * 根据busybox获取本地Mac
     *
     * @return
     */
    fun getLocalMacAddressFromBusybox(): String? {
        var result: String? = ""
        var Mac = ""
        result = callCmd("busybox ifconfig", "HWaddr")
        // 如果返回的result == null，则说明网络不可取
        if (result == null) {
            return "网络异常"
        }
        // 对该行数据进行解析
        // 例如：eth0 Link encap:Ethernet HWaddr 00:16:E8:3E:DF:67
        if (result.length > 0 && result.contains("HWaddr") == true) {
            Mac = result.substring(
                result.indexOf("HWaddr") + 6,
                result.length - 1
            )
            result = Mac
        }
        return result
    }

    private fun callCmd(cmd: String, filter: String): String? {
        var result: String? = ""
        var line = ""
        try {
            val proc = Runtime.getRuntime().exec(cmd)
            val `is` = InputStreamReader(proc.inputStream)
            val br = BufferedReader(`is`)
            while (br.readLine().also { line = it } != null
                && line.contains(filter) == false
            ) {
                result += line
            }
            result = line
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return result
    }

    /**
     * 获取手机序列号
     *
     * @return 手机序列号
     */
    @SuppressLint("NewApi", "MissingPermission")
    fun getSerialNumber(context: Context): String {
        var serial = ""
        try {
            serial = if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) { //8.0+
                Build.SERIAL
            } else { //8.0-
                val c = Class.forName("android.os.SystemProperties")
                val get = c.getMethod("get", String::class.java)
                get.invoke(c, "ro.serialno") as String
            }
        } catch (e: Exception) {
            e.printStackTrace()
            LogUtils.d("读取设备序列号异常：$e")
        }
        if (TextUtils.isEmpty(serial) || serial.toLowerCase() == "unknown") {
            serial = Settings.Secure.getString(
                context.contentResolver,
                Settings.Secure.ANDROID_ID
            )
        }
        return if (TextUtils.isEmpty(serial) && !serial.contains("CBTXPB")) {
            "CBTXPB$serial"
        } else {
            serial
        }
    }

    fun getSerial(context: Context): String? {
        if (serial != null) {
            return serial
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            if (context.checkSelfPermission(Manifest.permission.READ_PHONE_STATE)
                == PackageManager.PERMISSION_GRANTED
            ) {
                try {
                    serial = Build.getSerial()
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }
        } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {
            serial = Build.SERIAL
        } else {
            try {
                val c = Class.forName("android.os.SystemProperties")
                val get = c.getMethod("get", String::class.java)
                serial = get.invoke(c, "ro.serialno") as String
            } catch (e: ClassNotFoundException) {
                e.printStackTrace()
            }
        }
        if (serial == null) {
            serial = "N/A"
        }
        return serial
    }

}